package com.micro.ai.template.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.micro.ai.commons.exception.BusinessException;
import com.micro.ai.template.entity.ExecutionLog;
import com.micro.ai.template.mapper.ExecutionLogMapper;
import com.micro.ai.template.service.ExecutionLogService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 执行日志Service实现
 *
 * @author micro-ai
 * @since 0.0.1
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class ExecutionLogServiceImpl extends ServiceImpl<ExecutionLogMapper, ExecutionLog>
        implements ExecutionLogService {

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ExecutionLog createLog(ExecutionLog executionLog) {
        log.info("创建执行日志, requestId: {}", executionLog.getRequestId());
        
        executionLog.setCreatedAt(LocalDateTime.now());
        this.save(executionLog);
        
        return executionLog;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateLog(String logId, ExecutionLog executionLog) {
        log.info("更新执行日志, logId: {}", logId);
        
        ExecutionLog existing = this.getById(logId);
        if (existing == null) {
            throw new BusinessException("日志记录不存在");
        }
        
        executionLog.setId(logId);
        this.updateById(executionLog);
    }

    @Override
    public IPage<ExecutionLog> getLogsByExecutionId(String executionId, Page<ExecutionLog> page) {
        LambdaQueryWrapper<ExecutionLog> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ExecutionLog::getRequestId, executionId)
                .orderByDesc(ExecutionLog::getCreatedAt);
        
        return this.page(page, wrapper);
    }

    @Override
    public IPage<ExecutionLog> getLogsByAgentId(String agentId, Page<ExecutionLog> page) {
        LambdaQueryWrapper<ExecutionLog> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ExecutionLog::getAgentId, agentId)
                .orderByDesc(ExecutionLog::getCreatedAt);
        
        return this.page(page, wrapper);
    }

    @Override
    public Map<String, Object> getStatistics(String agentId, int days) {
        LocalDateTime startTime = LocalDateTime.now().minusDays(days);
        
        LambdaQueryWrapper<ExecutionLog> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ExecutionLog::getAgentId, agentId)
                .ge(ExecutionLog::getCreatedAt, startTime);
        
        List<ExecutionLog> logs = this.list(wrapper);
        
        Map<String, Object> stats = new HashMap<>();
        stats.put("totalCount", logs.size());
        stats.put("successCount", logs.stream().filter(log -> "success".equals(log.getStatus())).count());
        stats.put("failureCount", logs.stream().filter(log -> "failure".equals(log.getStatus())).count());
        stats.put("averageDuration", logs.stream()
                .filter(log -> log.getProcessingTimeMs() != null)
                .mapToLong(ExecutionLog::getProcessingTimeMs)
                .average()
                .orElse(0.0));
        
        return stats;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int cleanExpiredLogs(int days) {
        log.info("清理过期日志, days: {}", days);
        
        LocalDateTime expireTime = LocalDateTime.now().minusDays(days);
        
        LambdaQueryWrapper<ExecutionLog> wrapper = new LambdaQueryWrapper<>();
        wrapper.lt(ExecutionLog::getCreatedAt, expireTime);
        
        int count = (int) this.count(wrapper);
        this.remove(wrapper);
        
        log.info("清理完成, 删除记录数: {}", count);
        return count;
    }
}

